package config

import (
	"article_vote/models"
	"errors"
	"fmt"
	"github.com/go-redis/redis"
	"github.com/go-yaml/yaml"
	"io/ioutil"
	"path/filepath"
	"reflect"
	"strings"
	"time"
)

//配置文件结构体
type ConfigEngine struct {
	data map[string]interface{}
}

//存放Redis连接
var redisMap = map[string]*redis.Client{}

func InitConf(path string) {
	conf = NewConf()
	err := conf.LoadConf(path)
	if err != nil {
		panic(err)
	}
}

func InitRedis() error {
	//初始化Redis
	redisConf = &redis.Options{
		Addr:               conf.Get("RedisCommon.Addr", "127.0.0.1:6379").(string),
		Password:           conf.Get("RedisCommon.Password", "").(string),
		DB:                 conf.Get("RedisCommon.DB", 0).(int),
	}
	redisDB := redis.NewClient(redisConf)
	_, err := redisDB.Ping().Result()
	if err != nil {
		return err
	}
	redisDB.Set("test-start", time.Now().Unix(), 10 * time.Second)
	fmt.Println(redisDB.Get("test-start"))
	redisMap["default"] = redisDB
	return nil
}

func GetRedis(name string) (*redis.Client, error) {
	if _, ok := redisMap[name]; ok {
		return redisMap[name], nil
	}

	return nil, errors.New("get redis obj failed")
}

func InitMysql() error {
	setDbConf()
	err := mysqlConf.SetDbPool()              //建立db连接池
	err = mysqlConf.SetEngineName("default") //为每个db设置一个engine name
	return err
}

func CreateTable() error {
	if dbObj, err := GetDbObj("default"); err != nil {
		return err
	} else {
		dbObj.AutoMigrate(&models.Author{}, &models.Atricle{})
	}
	return nil
}

func NewConf() *ConfigEngine {
	return &ConfigEngine{}
}

//获取全部配置
func (c *ConfigEngine) GetData() map[string]interface{} {
	return c.data
}

//加载配置文件
func (c *ConfigEngine) LoadConf(path string) error {
	ext := filepath.Ext(path)

	switch ext {
	case ".yaml", ".yml":
		data, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}

		// yaml解析的时候c.data如果没有被初始化，会自动为你做初始化
		err = yaml.Unmarshal(data, &c.data)
		if err != nil {
			return errors.New("can not parse " + path + " config")
		}

		return nil
	default:
		panic("error path ext")
	}

	return nil
}

// 从配置文件中获取值
func (c *ConfigEngine) Get(name string, defaultValue interface{}) interface{} {
	path := strings.Split(name, ".")
	data := c.data
	for key, value := range path {
		v, ok := data[value]
		if !ok {
			break
		}

		if (key + 1) == len(path) {
			return v
		}
		if reflect.TypeOf(v).String() == "map[interface {}]interface {}" {
			data = convertInterfaceMap(v.(map[interface{}]interface{}))
		}
	}

	return defaultValue
}

func convertInterfaceMap(data map[interface{}]interface{}) map[string]interface{} {
	res := make(map[string]interface{})
	for key, value := range data{
		res[key.(string)] = value
	}
	return res
}

func setDbConf() {
	mysqlConf.Ip = conf.Get("MysqlConf.Ip", "127.0.0.1").(string)
	mysqlConf.Port = conf.Get("MysqlConf.Port", 3306).(int)
	mysqlConf.User = conf.Get("MysqlConf.User", "root").(string)
	mysqlConf.Password = conf.Get("MysqlConf.Password", "").(string)
	mysqlConf.Database = conf.Get("MysqlConf.Database", "test").(string)
	mysqlConf.MaxIdleConns = conf.Get("MysqlConf.MaxIdleConns", 2).(int)
	mysqlConf.MaxOpenConns = conf.Get("MysqlConf.MaxOpenConns", 4).(int)
	mysqlConf.ParseTime = conf.Get("MysqlConf.ParseTime", true).(bool)
	mysqlConf.SqlCmd = conf.Get("MysqlConf.SqlCmd", true).(bool)
	mysqlConf.UsePool = conf.Get("MysqlConf.UsePool", true).(bool)
}